<?php
//=======================================
//###################################
// Kayako Web Solutions
//
// Source Copyright 2001-2004 Kayako Web Solutions
// Unauthorized reproduction is not allowed
// License Number: $%LICENSE%$
// $Author: vshoor $ ($Date: 2007/02/13 06:47:44 $)
// $RCSfile: syncworks_sync.php,v $ : $Revision: 1.11 $ 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###################################
//=======================================


if (!defined("INSWIFT")) {
	trigger_error("Unable to process $PHP_SELF", E_USER_ERROR);
}

require_once ("./modules/teamwork/functions_syncworks.php");
require_once ("./modules/teamwork/functions_contacts.php");
require_once ("./modules/teamwork/functions_tasks.php");
require_once ("./modules/teamwork/functions_calendar.php");
require_once ("./includes/functions_xml.php");
require_once ("./includes/functions_winapp.php");
$xml = new XML;

$_swguid = $_POST["guid"];
$_guidid = loadGuidID($_swguid);

/**
* ###############################################
* SYNCHRONIZE
* ###############################################
*/
if ($eventaction == "syncworks")
{
	$_starttime = fetchmicrotime();

	$xmlarray = $xml->xml2tree(decodeWinappData(urldecode($_POST["xml"])));
	ob_start();
	print_r($xmlarray);
	$_xmlcontents = ob_get_contents();
	ob_end_clean();
	$_SWIFT["_debugdata"] .= "Parsed XML:\n".$_xmlcontents."\n";

	$_xmlstore = &$xmlarray["syncworks"][0]["children"];

	// ======= EXTENDED CONF PROTOCOL =======
	$_s2c = $_c2s = array();
	if (isset($_xmlstore["conf"]))
	{
		$_s2c["contacts"]["sync"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["contacts"][0]["attrs"]["sync"]);
		$_s2c["contacts"]["del"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["contacts"][0]["attrs"]["del"]);
		$_s2c["tasks"]["sync"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["tasks"][0]["attrs"]["sync"]);
		$_s2c["tasks"]["del"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["tasks"][0]["attrs"]["del"]);
		$_s2c["appointments"]["sync"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["appointments"][0]["attrs"]["sync"]);
		$_s2c["appointments"]["del"] = intval($_xmlstore["conf"][0]["children"]["s2c"][0]["children"]["appointments"][0]["attrs"]["del"]);

		$_c2s["contacts"]["sync"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["contacts"][0]["attrs"]["sync"]);
		$_c2s["contacts"]["del"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["contacts"][0]["attrs"]["del"]);
		$_c2s["contacts"]["priv"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["contacts"][0]["attrs"]["priv"]);
		$_c2s["tasks"]["sync"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["tasks"][0]["attrs"]["sync"]);
		$_c2s["tasks"]["del"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["tasks"][0]["attrs"]["del"]);
		$_c2s["tasks"]["priv"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["tasks"][0]["attrs"]["priv"]);
		$_c2s["appointments"]["sync"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["appointments"][0]["attrs"]["sync"]);
		$_c2s["appointments"]["del"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["appointments"][0]["attrs"]["del"]);
		$_c2s["appointments"]["priv"] = intval($_xmlstore["conf"][0]["children"]["c2s"][0]["children"]["appointments"][0]["attrs"]["priv"]);
	} else {
		$_s2c["contacts"]["sync"] = true;
		$_s2c["contacts"]["del"] = true;
		$_s2c["tasks"]["sync"] = true;
		$_s2c["tasks"]["del"] = true;
		$_s2c["appointments"]["sync"] = true;
		$_s2c["appointments"]["del"] = true;

		$_c2s["contacts"]["sync"] = true;
		$_c2s["contacts"]["del"] = true;
		$_c2s["contacts"]["priv"] = true;
		$_c2s["tasks"]["sync"] = true;
		$_c2s["tasks"]["del"] = true;
		$_c2s["tasks"]["priv"] = true;
		$_c2s["appointments"]["sync"] = true;
		$_c2s["appointments"]["del"] = true;
		$_c2s["appointments"]["priv"] = true;
	}

	ob_start();
	print_r($_c2s);
	print_r($_s2c);
	$_SWIFT["_debugdata"] .= "Extended Conf Protocol: \n". ob_get_contents() ."\n";
	ob_end_clean();

	$_contacts = &$_xmlstore["contacts"][0]["children"]["contact"];
	$_calendar = &$_xmlstore["calendar"][0]["children"]["appointment"];
	$_tasks = &$_xmlstore["tasks"][0]["children"]["task"];
	$_SWIFT["_debugdata"] .= "Sync Status: Contacts: ". count($_contacts) .", Calendar: ". count($_calendar) .", Tasks: ". count($_tasks) ."\n";
	$_SWIFT["_debugdata"] .= "Sync Status2: Contacts: ". count($xmlarray["syncworks"][0]["children"]["contacts"][0]["children"]["contact"]) .", Calendar: ". count($xmlarray["syncworks"][0]["children"]["calendar"][0]["children"]["appointment"]) .", Tasks: ". count($xmlarray["syncworks"][0]["children"]["tasks"][0]["children"]["task"]) ."\n";

	$entryidlist = $_datalist = $entrypointer = array();
	$_SWIFT["_debugdata"] .= "Incoming POST DATA:\n".$_POST["xml"]."\n";

	$_SWIFT["_debugdata"] .= "Incoming XML\n".decodeWinappData($_POST["xml"])."\n";

	// Process Contacts
	if (_is_array($_contacts))
	{
		$_SWIFT["_debugdata"] .= "Starting to Process Contacts\n";
		foreach ($_contacts as $key=>$val)
		{
			if (!_is_array($val["children"]["entry"]))
			{
				$_SWIFT["_debugdata"] .= "[ERROR] INVALID CONTACT ENTRY!!!\n";
				continue;
			}

			unset($entryid);
			foreach ($val["children"]["entry"] as $entrykey=>$entryval)
			{
				$entryname = $entryval["attrs"]["name"];
				$entryvalue = $entryval["values"][0];

				if ($entryname == "EntryID")
				{
					$_SWIFT["_debugdata"] .= "[ENTRYID]: Found Contact Entry ID: ". $entryvalue ."\n";
					$_datalist[$entryvalue] = array();
					$_datalist[$entryvalue]["type"] = TEAMWORK_CONTACT;
					$entryidlist[] = $entryvalue;
					$entrypointer[$entryvalue] = LINK_CONTACT;
					$entryid = $entryvalue;
				}

				$_datalist[$entryid][$entryname] = $entryvalue;
			}
		}
	}

	// Process Events
	if (_is_array($_calendar))
	{
		$_SWIFT["_debugdata"] .= "Starting to Process Events\n";
		foreach ($_calendar as $key=>$val)
		{
			if (!_is_array($val["children"]["entry"]))
			{
				$_SWIFT["_debugdata"] .= "[ERROR]: INVALID EVENT ENTRY!!!\n";
				continue;
			}

			unset($entryid);
			foreach ($val["children"]["entry"] as $entrykey=>$entryval)
			{
				$entryname = $entryval["attrs"]["name"];
				$entryvalue = $entryval["values"][0];

				if ($entryname == "EntryID")
				{
					$_SWIFT["_debugdata"] .= "Processing Event Entry ID: ". $entryvalue ."\n";
					$_datalist[$entryvalue] = array();
					$_datalist[$entryvalue]["type"] = TEAMWORK_EVENT;
					$entryidlist[] = $entryvalue;
					$entrypointer[$entryvalue] = LINK_EVENT;
					$entryid = $entryvalue;
				}

				$_datalist[$entryid][$entryname] = $entryvalue;
			}
		}
	}

	// Process Tasks
	if (_is_array($_tasks))
	{
		$_SWIFT["_debugdata"] .= "Starting to Process Tasks\n";
		foreach ($_tasks as $key=>$val)
		{
			if (!_is_array($val["children"]["entry"]))
			{
				$_SWIFT["_debugdata"] .= "[ERROR]: INVALID TASK ENTRY!!!\n";
				continue;
			}

			unset($entryid);
			foreach ($val["children"]["entry"] as $entrykey=>$entryval)
			{
				$entryname = $entryval["attrs"]["name"];
				$entryvalue = $entryval["values"][0];

				if ($entryname == "EntryID")
				{
					$_SWIFT["_debugdata"] .= "Processing Task Entry ID: ". $entryvalue ."\n";
					$_datalist[$entryvalue] = array();
					$_datalist[$entryvalue]["type"] = TEAMWORK_TASK;
					$entryidlist[] = $entryvalue;
					$entrypointer[$entryvalue] = LINK_TASK;
					$entryid = $entryvalue;
				}

				$_datalist[$entryid][$entryname] = $entryvalue;
			}
		}
	}

	// ======= LOAD THE ENTRY IDS FOR THIS GUID SYNCWORKS =======
	$_deletelist = $_deleteentrylist = $_updatelist = $_entrytypeidpointer = array();
	if (!empty($_guidid))
	{
		$_SWIFT["_debugdata"] .= "[OK]: Got the SW GUID: ". $_guidid .", Fetching the entry list assigned to this GUID\n";
		$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."calendarlinks` WHERE `guidid` = '". intval($_guidid) ."';");
		while ($dbCore->nextRecord())
		{
			$_SWIFT["_debugdata"] .= "[FETCH]: Received: ". $dbCore->Record["entryid"] ." - ". $dbCore->Record["linktype"] .", ". $dbCore->Record["typeid"] ."\n";
			$_entry = $_datalist[$dbCore->Record["entryid"]];
			$_entrytypeidpointer[$dbCore->Record["linktype"]][$dbCore->Record["typeid"]] = $dbCore->Record;

			if (!in_array($dbCore->Record["entryid"], $entryidlist))
			{
				// Ok this is an entry that was apparently not passed in during our sync but was added earlier from this same installation.. seems like someone deleted it from Outlook?
				$_SWIFT["_debugdata"] .= "[MSO DELETE]: Found an entry to be deleted from MS Outlook, Entry ID: ". $dbCore->Record["entryid"] .", Link type: ". $dbCore->Record["linktype"] .", Type ID: ". $dbCore->Record["typeid"] ."\n";
				$_deletelist[] = $dbCore->Record;
				$_deleteentrylist[] = $dbCore->Record["entryid"];
			} else if (!empty($_entry["EntryID"]) && MSODateToDateline($_entry["LastModificationTime"]) > $dbCore->Record["lastupdate"]) {
				// Entry has been modified?
				$_updatelist[] = $dbCore->Record;
				$_SWIFT["_debugdata"] .= "[SWIFT UPDATE]: Found an entry to be updated in SWIFT, Entry ID: ". $dbCore->Record["entryid"] .", Link type: ". $dbCore->Record["linktype"] .", Type ID: ". $dbCore->Record["typeid"] .", LastModificationTime: ". $_entry["LastModificationTime"] .", MSODateToDateline: ". MSODateToDateline($_entry["LastModificationTime"]) ." (". date("d M Y h:i:s A", MSODateToDateline($_entry["LastModificationTime"])) ."), Last Update: ". $dbCore->Record["lastupdate"] ." (". date("d M Y h:i:s A", $dbCore->Record["lastupdate"]) .")\n";
			}
		}
	} else {
		$_SWIFT["_debugdata"] .= "[WARNING]: SyncWorks GUID IS EMPTY\n";
	}

	// ======= PROCESS THE ENTRIES TO DELETE FROM SWIFT =======
	if (count($_deletelist))
	{
		$_SWIFT["_debugdata"] .= "[DEL STATUS]: We have entries to delete from SWIFT as they were deleted in Outlook\n";
		$_contactdellist = $_eventdellist = $_taskdellist = array();
		foreach ($_deletelist as $key=>$val)
		{
			if ($val["linktype"] == LINK_CONTACT)
			{
				$_SWIFT["_debugdata"] .= "[DEL]: Deleting Contact, Type ID: ". $val["typeid"] .", Entry ID: ". $val["entryid"] .", Last Update: ". date("d M Y h:i:s A", $val["lastupdate"]) .", Last SWIFT Update: ". date("d M Y h:i:s A", $val["lastswiftupdate"]) ."\n";
				$_contactdellist[] = $val["typeid"];
			} else if ($val["linktype"] == LINK_EVENT) {
				$_SWIFT["_debugdata"] .= "[DEL]: Deleting Event, Type ID: ". $val["typeid"] .", Entry ID: ". $val["entryid"] .", Last Update: ". date("d M Y h:i:s A", $val["lastupdate"]) .", Last SWIFT Update: ". date("d M Y h:i:s A", $val["lastswiftupdate"]) ."\n";
				$_eventdellist[] = $val["typeid"];
			} else if ($val["linktype"] == LINK_TASK) {
				$_SWIFT["_debugdata"] .= "[DEL]: Deleting Task, Type ID: ". $val["typeid"] .", Entry ID: ". $val["entryid"] .", Last Update: ". date("d M Y h:i:s A", $val["lastupdate"]) .", Last SWIFT Update: ". date("d M Y h:i:s A", $val["lastswiftupdate"]) ."\n";
				$_taskdellist[] = $val["typeid"];
			}
		}

		if (count($_contactdellist) && $_c2s["contacts"]["del"] == true) // Delete Contacts
		{
			deleteContacts($_contactdellist, $_guidid);
		}
		if (count($_eventdellist) && $_c2s["appointments"]["del"] == true) // Delete Events
		{
			deleteCalendarEvents($_eventdellist, $_guidid);
		}
		if (count($_taskdellist) && $_c2s["tasks"]["del"] == true) // Delete Tasks
		{
			deleteCalendarTasks($_taskdellist, $_guidid);
		}
	}

	// ======= PROCESS DELETED ENTRIES FROM SWIFT =======
	$_SWIFT["_debugdata"] .= "[DEL STATUS]: Processing Entries to delete from Outlook as they were deleted in SWIFT\n";
	$_deletelog = $_ignoreentryid = array();
	$_lastsync = $_SWIFT["syncworkscache"][$_SWIFT["staff"]["staffid"]]["lastsync"];
	if (empty($_lastsync))
	{
		$_lastsync = DATENOW;
	}
	$_SWIFT["_debugdata"] .= "[DEL STATUS]: Last Sync: ". date("d M Y h:i:s A", $_lastsync) .", Time Now: ". date("d M Y h:i:s A", DATENOW) ."\n";


	$_SWIFT["_debugdata"] .= "[DEL STATUS]: Fetching entries...\n";
	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."twdeletelog` WHERE `dateline` >= '". intval($_lastsync) ."';");
	while ($dbCore->nextRecord())
	{
		if (!empty($dbCore->Record["entryid"]) && !in_array($dbCore->Record["entryid"], $_deleteentrylist) && $dbCore->Record["guidid"] != $_guidid)
		{
			$_SWIFT["_debugdata"] .= "[DEL STATUS]: Found Entry!, EntryID: ". $dbCore->Record["entryid"] .", Type ID: ". $dbCore->Record["typeid"] .", Entry Type: ". $dbCore->Record["entrytype"] ."\n";
			$_deletelog[] = $dbCore->Record;
			$_ignoreentryid[] = $dbCore->Record["entryid"];
		}
	}

	// Make EntryID SQL
	$_contacttypeid = $_eventtypeid = $_tasktypeid = $_contactstore = $_eventstore = $_taskstore = array();
//	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."calendarlinks` WHERE `entryid` IN (". buildIN($entryidlist) .");");
	$_SWIFT["_debugdata"] .= "[FETCH]: Fetching all entries that exist for the current GUID\n";
	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."calendarlinks` WHERE `guidid` = '". intval($_guidid) ."';");
	while ($dbCore->nextRecord())
	{
		unset($entrypointer[$dbCore->Record["entryid"]]);

		$_datalist[$dbCore->Record["entryid"]]["typeid"] = intval($dbCore->Record["typeid"]);

		if ($dbCore->Record["linktype"] == LINK_CONTACT)
		{
			$_SWIFT["_debugdata"] .= "[FETCH]: Found CONTACT Entry!, EntryID: ". $dbCore->Record["entryid"] .", Type ID: ". $dbCore->Record["typeid"] .", Entry Type: ". $dbCore->Record["entrytype"] ."\n";
			$_contacttypeid[] = $dbCore->Record["typeid"];
			$_contactstore[$dbCore->Record["typeid"]][] = $dbCore->Record["entryid"];
		} else if ($dbCore->Record["linktype"] == LINK_EVENT) {
			$_SWIFT["_debugdata"] .= "[FETCH]: Found EVENT Entry!, EntryID: ". $dbCore->Record["entryid"] .", Type ID: ". $dbCore->Record["typeid"] .", Entry Type: ". $dbCore->Record["entrytype"] ."\n";
			$_eventtypeid[] = $dbCore->Record["typeid"];
			$_eventstore[$dbCore->Record["typeid"]][] = $dbCore->Record["entryid"];
		} else if ($dbCore->Record["linktype"] == LINK_TASK) {
			$_SWIFT["_debugdata"] .= "[FETCH]: Found TASK Entry!, EntryID: ". $dbCore->Record["entryid"] .", Type ID: ". $dbCore->Record["typeid"] .", Entry Type: ". $dbCore->Record["entrytype"] ."\n";
			$_tasktypeid[] = $dbCore->Record["typeid"];
			$_taskstore[$dbCore->Record["typeid"]][] = $dbCore->Record["entryid"];
		}
	}

	// Ok, Now we go through entrypointer, any entries are the new one added to MS Outlook and need to be added to SWIFT
	$_SWIFT["_debugdata"] .= "[STATUS]: We are now going through entrypointer and checking to see if any new data needs to be added into SWIFT from MS Outlook\n";
	foreach ($entrypointer as $key=>$val)
	{
		$_entry = $_datalist[$key];

		if (empty($_entry["EntryID"]))
		{
			$_SWIFT["_debugdata"] .= "[ERROR]: Entry ID IS EMPTY!!\n";
			continue;
		}
		$_SWIFT["_debugdata"] .= "[STATUS]: Processing Entry: ". $_entry["EntryID"] . "-".$_c2s["contacts"]["sync"] ."\n";

		if ($_entry["type"] == TEAMWORK_CONTACT && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["contacts"]["sync"])
		{
			// Add new Contact
			$args = MSOContactEntryToSWIFT(&$_entry);
			$_icontactid = insertContact(iif($_c2s["contacts"]["priv"], SWIFTPRIVATE, SWIFTPUBLIC), $args);
			$_SWIFT["_debugdata"] .= "[INSERT]: Inserting new Contact: ". $args["fullname"] .", Last Modification Time: ". $_entry["LastModificationTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["LastModificationTime"])) .")" ."\n";
			if (!empty($_icontactid))
			{
				updateCalendarLink(LINK_CONTACT, $_entry["EntryID"], $_icontactid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]), DATENOW);

				$_contacttypeid[] = $_icontactid;
			}
		} else if ($_entry["type"] == TEAMWORK_EVENT && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["appointments"]["sync"]) {
			// Add new Event
			$_ieventid = insertEvent(_msodata($_entry["Subject"]), iif($_c2s["appointments"]["priv"], SWIFTPRIVATE, SWIFTPUBLIC), $_SWIFT["staff"]["staffid"], iif($_entry["AllDayEvent"]=="true","1","0"), MSODateToDateline($_entry["StartTime"]), MSODateToDateline($_entry["EndTime"]), ACTIVITY_APPOINTMENT, _msodata($_entry["Location"]), _msodata($_entry["Body"]), 0, 0, 0);
			$_SWIFT["_debugdata"] .= "[INSERT]: Inserting new Event: ". $_entry["Subject"] .", StartTime: ". $_entry["StartTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["StartTime"])) ."), EndTime: ". $_entry["EndTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["EndTime"])) .")" ."\n";
			if (!empty($_ieventid))
			{
				updateCalendarLink(LINK_EVENT, $_entry["EntryID"], $_ieventid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]), DATENOW);

				$_eventtypeid[] = $_ieventid;
			}
		} else if ($_entry["type"] == TEAMWORK_TASK && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["tasks"]["sync"]) {
			// Add new Task
			$_itaskid = insertCalendarTask(_msodata($_entry["Subject"]), iif($_c2s["tasks"]["priv"], SWIFTPRIVATE, SWIFTPUBLIC), $_SWIFT["staff"]["staffid"], MSODateToDateline($_entry["DueDate"]), MSODateToDateline($_entry["StartDate"]), 0, iif($_entry["Completed"]=="true", 1, 0), $_entry["PercentComplete"], 0, ($_entry["Status"]+1), 0, _msodata($_entry["Body"]));
			$_SWIFT["_debugdata"] .= "[INSERT]: Inserting new Task: ". $_entry["Subject"] .", Due Date: ". $_entry["DueDate"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["DueDate"])) ."), Start Date: ". $_entry["StartDate"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["StartDate"])) .")" ."\n";
			if (!empty($_itaskid))
			{
				updateCalendarLink(LINK_TASK, $_entry["EntryID"], $_itaskid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]), DATENOW);

				$_tasktypeid[] = $_itaskid;
			}
		}
	}

	// ======= PROCESS ENTRIES THAT WERE UPDATED IN MS OUTLOOK =======
	$_SWIFT["_debugdata"] .= "[UPDATE PROCESS]: Processing entries that were updated in MS Outlook...\n";
	foreach ($_updatelist as $key=>$val)
	{
		$_entry = $_datalist[$val["entryid"]];
		$_typeid = $val["typeid"];

		if (empty($_entry["EntryID"]))
		{
			continue;
		}

		if ($_entry["type"] == TEAMWORK_CONTACT && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["contacts"]["sync"] == true)
		{
			$args = MSOContactEntryToSWIFT(&$_entry);
			updateContact($_typeid, SWIFTPRIVATE, $args);
			$_SWIFT["_debugdata"] .= "[UPDATE]: Updating Contact: ". $args["fullname"] .", Last Modification Time: ". $_entry["LastModificationTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["LastModificationTime"])) .")" ."\n";
			_updateCalendarLink(LINK_CONTACT, $_entry["EntryID"], $_typeid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]));
		} else if ($_entry["type"] == TEAMWORK_EVENT && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["appointments"]["sync"] == true) {
			updateEvent($_typeid, _msodata($_entry["Subject"]), SWIFTPRIVATE, $_SWIFT["staff"]["staffid"], iif($_entry["AllDayEvent"]=="true","1","0"), MSODateToDateline($_entry["StartTime"]), MSODateToDateline($_entry["EndTime"]), ACTIVITY_APPOINTMENT, _msodata($_entry["Location"]), _msodata($_entry["Body"]), 0, 0, 0);

			$_SWIFT["_debugdata"] .= "[UPDATE]: Updating Event: ". $_entry["Subject"] .", StartTime: ". $_entry["StartTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["StartTime"])) ."), EndTime: ". $_entry["EndTime"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["EndTime"])) .")" ."\n";

			_updateCalendarLink(LINK_EVENT, $_entry["EntryID"], $_typeid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]));
		} else if ($_entry["type"] == TEAMWORK_TASK && !in_array($_entry["EntryID"], $_ignoreentryid) && $_c2s["tasks"]["sync"] == true) {
			updateCalendarTask($_typeid, _msodata($_entry["Subject"]), SWIFTPRIVATE, $_SWIFT["staff"]["staffid"], MSODateToDateline($_entry["DueDate"]), MSODateToDateline($_entry["StartDate"]), 0, iif($_entry["Completed"]=="true", 1, 0), $_entry["PercentComplete"], 0, ($_entry["Status"]+1), 0, _msodata($_entry["Body"]));

			$_SWIFT["_debugdata"] .= "[UPDATE]: Updating Task: ". $_entry["Subject"] .", Due Date: ". $_entry["DueDate"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["DueDate"])) ."), Start Date: ". $_entry["StartDate"]." (". date("d M Y h:i:s A", MSODateToDateline($_entry["StartDate"])) .")" ."\n";

			_updateCalendarLink(LINK_TASK, $_entry["EntryID"], $_typeid, $_guidid, MSODateToDateline($_entry["LastModificationTime"]));
		}
	}

	// Now we need to see which entries are in SWIFT and which arent in Outlook...
	$_ocontactid = $_oeventid = $_otaskid = $_pointersql = array();

	// Process Contacts
	$dbCore->query("SELECT `contactid`, `lastupdate` FROM `". TABLE_PREFIX ."contacts` WHERE (`contacttype` = '". SWIFTPUBLIC ."') OR (`contacttype` = '". SWIFTPRIVATE ."' AND `staffid` = '". intval($_SWIFT["staff"]["staffid"]) ."');");
	while ($dbCore->nextRecord())
	{
		$_linkentry = $_entrytypeidpointer[LINK_CONTACT][$dbCore->Record["contactid"]];

		if ($_linkentry["lastswiftupdate"] < $dbCore->Record["lastupdate"] && !empty($_linkentry["entryid"])) {
			if (!empty($_linkentry["lastswiftupdate"]))
			{
				$_ocontactid[] = $dbCore->Record["contactid"];
			}
			_updateCalendarLink(LINK_CONTACT, $_linkentry["entryid"], $dbCore->Record["contactid"], $_guidid, 0, $dbCore->Record["lastupdate"]);
		} else if (!in_array($dbCore->Record["contactid"], $_contacttypeid)) {
			// Add to MS Outlook as it isnt in the entry list
			$_ocontactid[] = $dbCore->Record["contactid"];
		}
	}

	// Process the Tasks
	$dbCore->query("SELECT `calendartaskid`, `tasktype`, `ownerstaffid`, `lastupdate` FROM `". TABLE_PREFIX ."calendartasks` WHERE (`tasktype` = '". SWIFTPUBLIC ."') OR (`tasktype` = '". SWIFTPRIVATE ."' AND `staffid` = '". intval($_SWIFT["staff"]["staffid"]) ."');");
	while ($dbCore->nextRecord())
	{
		$_linkentry = $_entrytypeidpointer[LINK_TASK][$dbCore->Record["calendartaskid"]];

		if ($dbCore->Record["tasktype"] == SWIFTPUBLIC && $dbCore->Record["ownerstaffid"] != $_SWIFT["staff"]["staffid"] && !empty($dbCore->Record["ownerstaffid"]))
		{
			continue;
		}

		if ($_linkentry["lastswiftupdate"] < $dbCore->Record["lastupdate"] && !empty($_linkentry["entryid"])) {
			if (!empty($_linkentry["lastswiftupdate"]))
			{
				$_otaskid[] = $dbCore->Record["calendartaskid"];
			}
			_updateCalendarLink(LINK_TASK, $_linkentry["entryid"], $dbCore->Record["calendartaskid"], $_guidid, 0, $dbCore->Record["lastupdate"]);
		} else if (!in_array($dbCore->Record["calendartaskid"], $_tasktypeid)) {
			// Add to MS Outlook as it isnt in the entry list
			$_otaskid[] = $dbCore->Record["calendartaskid"];
		}
	}

	// Process the Events
	$dbCore->query("SELECT `calendareventid`, `eventtype`, `ownerstaffid`, `lastupdate` FROM `". TABLE_PREFIX ."calendarevents` WHERE (`eventtype` = '". SWIFTPUBLIC ."') OR (`eventtype` = '". SWIFTPRIVATE ."' AND `staffid` = '". intval($_SWIFT["staff"]["staffid"]) ."');");
	while ($dbCore->nextRecord())
	{
		$_linkentry = $_entrytypeidpointer[LINK_EVENT][$dbCore->Record["calendareventid"]];

		if ($dbCore->Record["eventtype"] == SWIFTPUBLIC && $dbCore->Record["ownerstaffid"] != $_SWIFT["staff"]["staffid"] && !empty($dbCore->Record["ownerstaffid"]))
		{
			continue;
		}

		if ($_linkentry["lastswiftupdate"] < $dbCore->Record["lastupdate"] && !empty($_linkentry["entryid"])) {
			if (!empty($_linkentry["lastswiftupdate"]))
			{
				$_oeventid[] = $dbCore->Record["calendareventid"];
			}
			_updateCalendarLink(LINK_EVENT, $_linkentry["entryid"], $dbCore->Record["calendareventid"], $_guidid, 0, $dbCore->Record["lastupdate"]);
		} else if (!in_array($dbCore->Record["calendareventid"], $_eventtypeid)) {
			// Add to MS Outlook as it isnt in the entry list
			$_oeventid[] = $dbCore->Record["calendareventid"];
		}
	}

	// ======= PROCESS THE TO ADD DATA =======
	$_msocontacts = $_msotasks = $_msoevents = array();

	// First get the contacts if any
	if (count($_ocontactid))
	{
		$dbCore->query("SELECT contacts.*, calendardata.contents AS body FROM `". TABLE_PREFIX ."contacts` AS contacts LEFT JOIN `". TABLE_PREFIX."calendardata` AS calendardata ON (calendardata.typeid = contacts.contactid) WHERE `contactid` IN (". buildIN($_ocontactid) .") AND calendardata.datatype = '". TEAMWORK_CONTACT ."';");
		while ($dbCore->nextRecord())
		{
			$_msocontacts[$dbCore->Record["contactid"]] = $dbCore->Record;
		}
	}

	// Get the Tasks
	if (count($_otaskid))
	{
		$dbCore->query("SELECT calendartasks.*, calendardata.contents AS body FROM `". TABLE_PREFIX ."calendartasks` AS calendartasks LEFT JOIN `". TABLE_PREFIX."calendardata` AS calendardata ON (calendardata.typeid = calendartasks.calendartaskid) WHERE calendartasks.calendartaskid IN (". buildIN($_otaskid) .") AND calendardata.datatype = '". TEAMWORK_TASK ."';");
		while ($dbCore->nextRecord())
		{
			$_msotasks[$dbCore->Record["calendartaskid"]] = $dbCore->Record;
		}
	}

	// Now the events
	if (count($_oeventid))
	{
		$dbCore->query("SELECT calendarevents.*, calendardata.contents AS body FROM `". TABLE_PREFIX ."calendarevents` AS calendarevents LEFT JOIN `". TABLE_PREFIX."calendardata` AS calendardata ON (calendardata.typeid = calendarevents.calendareventid) WHERE calendarevents.calendareventid IN (". buildIN($_oeventid) .") AND calendardata.datatype = '". TEAMWORK_EVENT ."';");
		while ($dbCore->nextRecord())
		{
			$_msoevents[$dbCore->Record["calendareventid"]] = $dbCore->Record;
		}
	}

	// ======= ADD THE NECESSARY STUFF TO OUTLOOK =======
	$xml->addParentTag("syncworks");

		// ======= BEGIN DELETE LOG =======
		$xml->addParentTag("deletelog");
			foreach ($_deletelog as $key=>$val)
			{
				if (in_array($val["entryid"], $_deleteentrylist))
				{
					continue;
				}

				// ======= EXTENDED PROTOCOL CHECK =======
				if ($val["entrytype"] == TEAMWORK_TASK && !$_s2c["tasks"]["del"])
				{
					continue;
				} else if ($val["entrytype"] == TEAMWORK_CONTACT && !$_s2c["contacts"]["del"]) {
					continue;
				} else if ($val["entrytype"] == TEAMWORK_EVENT && !$_s2c["appointments"]["del"]) {
					continue;
				}

				if ($val["entrytype"] == TEAMWORK_TASK)
				{
					$_entrytype = "task";
				} else if ($val["entrytype"] == TEAMWORK_CONTACT) {
					$_entrytype = "contact";
				} else if ($val["entrytype"] == TEAMWORK_EVENT) {
					$_entrytype = "event";
				}
				$xml->addParentTag("delentry");
					$xml->addTag("entrytype", $_entrytype);
					$xml->addTag("entryid", $val["entryid"]);
				$xml->endParentTag("delentry");
			}
		$xml->endParentTag("deletelog");
		// ======= END DELETE LOG =======

		// ======= BEGIN CONTACTS =======
		if ($_s2c["contacts"]["sync"])
		{
			$xml->addParentTag("contacts");
			foreach ($_msocontacts as $key=>$val)
			{
				$xml->addParentTag("contact");
				$xml->addTag("entry", $key, array("name" => "swiftentryid"));
				if (_is_array($_contactstore[$val["contactid"]]))
				{
					foreach ($_contactstore[$val["contactid"]] as $entrykey=>$entryval)
					{
						$xml->addTag("entry", $entryval, array("name" => "EntryID"));
					}
				} else {
					$xml->addTag("entry", "", array("name" => "EntryID"));
				}

				$xml->addTag("entry", $val["fullname"], array("name" => "FullName"));
				$xml->addTag("entry", $val["jobtitle"], array("name" => "JobTitle"));
				$xml->addTag("entry", $val["initials"], array("name" => "Initials"));
				$xml->addTag("entry", "", array("name" => "Categories"));
				$xml->addTag("entry", $val["email1address"], array("name" => "Email1Address"));
				$xml->addTag("entry", $val["email2address"], array("name" => "Email2Address"));
				$xml->addTag("entry", $val["email3address"], array("name" => "Email3Address"));
				$xml->addTag("entry", $val["customerid"], array("name" => "CustomerID"));
				$xml->addTag("entry", $val["mobiletelephonenumber"], array("name" => "MobileTelephoneNumber"));
				$xml->addTag("entry", $val["cartelephonenumber"], array("name" => "CarTelephoneNumber"));
				$xml->addTag("entry", $val["pagernumber"], array("name" => "PagerNumber"));
				$xml->addTag("entry", $val["othertelephonenumber"], array("name" => "OtherTelephoneNumber"));
				$xml->addTag("entry", $val["imaddress"], array("name" => "IMAddress"));

				$xml->addTag("entry", $val["companyname"], array("name" => "CompanyName"));
				$xml->addTag("entry", $val["department"], array("name" => "Department"));
				$xml->addTag("entry", $val["officelocation"], array("name" => "OfficeLocation"));
				$xml->addTag("entry", $val["businessaddress"], array("name" => "BusinessAddress"));
				$xml->addTag("entry", $val["businesstelephonenumber"], array("name" => "BusinessTelephoneNumber"));
				$xml->addTag("entry", $val["business2telephonenumber"], array("name" => "Business2TelephoneNumber"));
				$xml->addTag("entry", $val["businessfaxnumber"], array("name" => "BusinessFaxNumber"));
				$xml->addTag("entry", $val["businesshomepage"], array("name" => "BusinessHomePage"));

				$xml->addTag("entry", $val["homeaddress"], array("name" => "HomeAddress"));
				$xml->addTag("entry", $val["hometelephonenumber"], array("name" => "HomeTelephoneNumber"));
				$xml->addTag("entry", $val["home2telephonenumber"], array("name" => "Home2TelephoneNumber"));
				$xml->addTag("entry", $val["homefaxnumber"], array("name" => "HomeFaxNumber"));
				$xml->addTag("entry", datelineToMSODate($val["birthdaydateline"]), array("name" => "Birthday"));
				$xml->addTag("entry", datelineToMSODate($val["anniversarydateline"]), array("name" => "Anniversary"));

				$xml->addTag("entry", $val["mailingaddress"], array("name" => "MailingAddress"));
				$xml->addTag("entry", $val["otheraddress"], array("name" => "OtherAddress"));
				$xml->addTag("entry", $val["webpage"], array("name" => "WebPage"));
				$xml->addTag("entry", $val["assistantname"], array("name" => "AssistantName"));
				$xml->addTag("entry", $val["assistanttelephonenumber"], array("name" => "AssistantTelephoneNumber"));
				$xml->addTag("entry", $val["body"], array("name" => "Body"));
				$xml->endParentTag("contact");
			}
			$xml->endParentTag("contacts");
		}
		// ======= END CONTACTS =======


		// ======= BEGIN EVENTS =======
		if ($_s2c["appointments"]["sync"])
		{
			$xml->addParentTag("calendar");
			foreach ($_msoevents as $key=>$val)
			{
				$xml->addParentTag("appointment");
				$xml->addTag("entry", $key, array("name" => "swiftentryid"));
				if (_is_array($_eventstore[$val["calendareventid"]]))
				{
					foreach ($_eventstore[$val["calendareventid"]] as $entrykey=>$entryval)
					{
						$xml->addTag("entry", $entryval, array("name" => "EntryID"));
					}
				} else {
					$xml->addTag("entry", "", array("name" => "EntryID"));
				}

				$xml->addTag("entry", datelineToMSODate($val["startdateline"]), array("name" => "StartTime"));
				$xml->addTag("entry", iif($val["isalldayevent"]=="1", "true", "false"), array("name" => "AllDayEvent"));
				$xml->addTag("entry", datelineToMSODate($val["enddateline"]), array("name" => "EndTime"));
				$xml->addTag("entry", $val["duration"], array("name" => "Duration"));
				$xml->addTag("entry", "1", array("name" => "Importance"));
				$xml->addTag("entry", $val["location"], array("name" => "Location"));
				$xml->addTag("entry", "0", array("name" => "MeetingStatus"));
				$xml->addTag("entry", $val["subject"], array("name" => "Subject"));
				$xml->addTag("entry", $val["body"], array("name" => "Body"));
				$xml->endParentTag("appointment");
			}
			$xml->endParentTag("calendar");
		}
		// ======= END EVENTS =======


		// ======= BEGIN TASKS =======
		if ($_s2c["tasks"]["sync"])
		{
			$xml->addParentTag("tasks");
			foreach ($_msotasks as $key=>$val)
			{
				$xml->addParentTag("task");
				$xml->addTag("entry", $key, array("name" => "swiftentryid"));
				if (_is_array($_taskstore[$val["calendartaskid"]]))
				{
					foreach ($_taskstore[$val["calendartaskid"]] as $entrykey=>$entryval)
					{
						$xml->addTag("entry", $entryval, array("name" => "EntryID"));
					}
				} else {
					$xml->addTag("entry", "", array("name" => "EntryID"));
				}

				$xml->addTag("entry", $val["subject"], array("name" => "Subject"));
				$xml->addTag("entry", iif($val["iscomplete"]==1,"true","false"), array("name" => "Completed"));
				$xml->addTag("entry", "0", array("name" => "Status"));
				$xml->addTag("entry", datelineToMSODate($val["duedate"]), array("name" => "DueDate"));
				$xml->addTag("entry", datelineToMSODate($val["startdate"]), array("name" => "StartDate"));
				$xml->addTag("entry", $val["completepercent"], array("name" => "PercentComplete"));
				$xml->addTag("entry", "", array("name" => "Categories"));
				$xml->addTag("entry", $val["body"], array("name" => "Body"));
				$xml->endParentTag("task");
			}
			$xml->endParentTag("tasks");
		}
		// ======= END TASKS =======

	$xml->endTag("syncworks");
	$xml->echoXMLUTFWinapp();


	// ======= UPDATE THE SYNC CACHE =======
	$_endtime = fetchmicrotime();
	$_SWIFT["syncworkscache"][$_SWIFT["staff"]["staffid"]]["lastsync"] = DATENOW; // Used to send delete entries to MS Outlook
	$_SWIFT["syncworkscache"][$_SWIFT["staff"]["staffid"]]["timetaken"] = number_format(($_endtime-$_starttime), 4);
	global $datastore;
	$datastore->update("syncworkscache", $_SWIFT["syncworkscache"]);

	ob_start();
//	echo $_SWIFT["_debugdata"];
//	print_r($_entrytypeidpointer);
//	print_r($_deletelist);
//	print_r($_POST);
echo $_xmlcontents;
	$contents = ob_get_contents();
	ob_end_clean();

//	$contents = $xml->returnXML()."\n\n\n#############################################\n\n\n".$contents;

//	$fp = fopen("./cache/sync.txt", "w+");
//	fwrite($fp, $contents);
//	fclose($fp);







/**
* ###############################################
* UPDATE ENTRY LINKS
* ###############################################
*/
} else if ($eventaction == "updateentries") {
	$xmlarray = $xml->xml2tree(urldecode($_POST["xml"]));
	$_xmlstore = &$xmlarray["syncworks"][0]["children"];
	$_entryupdate = $_xmlstore["entryupdate"];

	$_sql = array();

	foreach ($_entryupdate as $key=>$val)
	{
		$_type = $val["children"]["type"][0]["values"][0];
		$_swiftentryid = $val["children"]["swiftentryid"][0]["values"][0];
		$_entryid = $val["children"]["entryid"][0]["values"][0];

		if (empty($_entryid))
		{
			continue;
		}

		if ($_type == "contact")
		{
			$linktype = LINK_CONTACT;
		} else if ($_type == "appointment") {
			$linktype = LINK_EVENT;
		} else if ($_type == "task") {
			$linktype = LINK_TASK;
		} else {
			continue;
		}

		$_sql[] = "('". intval($linktype) ."', '". $dbCore->escape($_entryid) ."', '". intval($_swiftentryid) ."', '". intval($_guidid) ."')";
	}

	if (count($_sql))
	{
		$dbCore->query("REPLACE INTO `". TABLE_PREFIX ."calendarlinks` (`linktype`, `entryid`, `typeid`, `guidid`) VALUES ". implode(",",$_sql) .";");
	}

	ob_start();
	print_r($_sql);
	print_r($_POST);
	$contents = ob_get_contents();
	ob_end_clean();

//	$fp = fopen("./cache/entryupdate.txt", "w+");
//	fwrite($fp, $contents);
//	fclose($fp);

	echoWinappData("1");



}
?>